package com.example.aigc_education.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.aigc_education.common.BusinessException;
import com.example.aigc_education.domain.Paper;
import com.example.aigc_education.domain.Plan;
import com.example.aigc_education.domain.Theme;
import com.example.aigc_education.domain.dto.TestInfoDTO;
import com.example.aigc_education.domain.dto.ThemeStudyTimeDTO;
import com.example.aigc_education.domain.request.*;
import com.example.aigc_education.domain.vo.*;
import com.example.aigc_education.enums.ThemeCompletionStatus;
import com.example.aigc_education.mapper.PaperMapper;
import com.example.aigc_education.mapper.PlanMapper;
import com.example.aigc_education.repository.ThemeStudyTimeRepository;
import com.example.aigc_education.service.ThemeService;
import com.example.aigc_education.mapper.ThemeMapper;
import com.example.aigc_education.service.converter.ThemeConverter;
import com.example.aigc_education.utils.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
* @author 23918
* @description 针对表【stu_theme(学习计划表)】的数据库操作Service实现
* @createDate 2024-11-03 22:18:22
*/
@Service
public class ThemeServiceImpl extends ServiceImpl<ThemeMapper, Theme>
    implements ThemeService{
    @Resource
    private ThemeMapper themeMapper;

    @Resource
    private PlanMapper planMapper;

    @Resource
    private PaperMapper paperMapper;

    @Resource
    private ThemeConverter themeConverter;


    @Resource
    private ThemeStudyTimeRepository themeStudyTimeRepository;

    @Override
    public boolean addTheme(AddThemeRequest addThemeRequest) {
        try {
            Theme theme = themeConverter.addThemeRequestToTheme(addThemeRequest);
            themeMapper.insert(theme);
            return true;
        } catch (Exception e) {
            throw new BusinessException("添加失败");
        }
    }

    @Transactional
    @Override
    public AddThemeRespVO addThemeV2(AddThemeV2Request request) {
        try {
            Theme theme = themeMapper.selectById(request.getSuperiorThemeId());
            Long planId = theme.getPlanId();
            Plan plan = planMapper.selectById(planId);
            Theme addTheme = new Theme();
            addTheme.setPlanId(plan.getPlanId());
            addTheme.setThemeTitle(request.getThemeTitle());
            addTheme.setSuperiorThemeId(request.getSuperiorThemeId());
            themeMapper.insert(addTheme);
            addTheme = themeMapper.selectById(addTheme.getThemeId());
            //如果父主题的状态为2，则将父子题目状态改为1
            if (theme.getCompletionStatus() == ThemeCompletionStatus.COMPLETED.getValue()) {
                theme.setCompletionStatus(ThemeCompletionStatus.IN_PROGRESS.getValue());
            }
            //重新计算计划进度
            plan.setCompletionProgress(countPlanProgress(planId));
            planMapper.updateById(plan);

            return new AddThemeRespVO(addTheme.getThemeId(), addTheme.getThemeTitle(),ThemeCompletionStatus.fromValue(addTheme.getCompletionStatus()).getTitle());
        } catch (Exception e) {
            throw new BusinessException("添加失败");
        }
    }

    @Override
    public UpdateThemeTitleRespVO updateThemeTitle(UpdateThemeTitleRequest request) {
        try {
            Theme theme = themeMapper.selectById(request.getThemeId());
            theme.setThemeTitle(request.getNewThemeTitle());
            themeMapper.updateById(theme);
            return new UpdateThemeTitleRespVO(theme.getThemeId(), theme.getThemeTitle());
        } catch (Exception e) {
            throw new BusinessException("更新失败");
        }
    }

    private double countPlanProgress(Long planId) {
        LambdaQueryWrapper<Theme> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Theme::getPlanId, planId)
                .eq(Theme::getStatus, 1);
        //将算出来的总主题数和已完成的主题数相除得到小数点后两位的进度
        int totalThemes = Math.toIntExact(themeMapper.selectCount(queryWrapper));
        queryWrapper.eq(Theme::getCompletionStatus, ThemeCompletionStatus.COMPLETED.getValue());
        int completedThemes = Math.toIntExact(themeMapper.selectCount(queryWrapper));
        //将算出来的总主题数和已完成的主题数相除得到小数点后两位的进度,只保留后两位
        return  (double) completedThemes / totalThemes;
    }

//方案1
//    @Override
//    public List<ThemeVO> showThemeTree(Long planId) {
//        LambdaQueryWrapper<Theme> queryWrapper = new LambdaQueryWrapper<>();
//        //通过主题id筛选paper
//        queryWrapper.eq(Theme::getPlanId, planId);
//        //筛选出有效的测验
//        queryWrapper.eq(Theme::getStatus, 1);
//        List<Theme> themes = themeMapper.selectList(queryWrapper);
//        return themeConverter.themesToThemeVOs(themes);
//    }

    //方案2
    @Override
    public ThemeTreeVO showThemeTree(Long planId) {
        Plan plan = planMapper.selectById(planId);
        ThemeTreeVO themeTreeVO = new ThemeTreeVO();
        themeTreeVO.setPlanId(planId);
        themeTreeVO.setPlanName(plan.getPlanName());
        //设置一级主题
        themeTreeVO.setThemeTitle(plan.getThemeTitle());
        //筛选出二级主题
        LambdaQueryWrapper<Theme> secondThemeQuery = setThemeTreeQueryWrapper(planId, 0L);
        List<Theme> secondThemes = themeMapper.selectList(secondThemeQuery);
        List<ThemeVO> secondThemeVOS = themeConverter.themesToThemeVOs(secondThemes);
        for (ThemeVO secondThemeVO : secondThemeVOS) {
            //筛选出三级主题
            Long secondThemeId = secondThemeVO.getThemeId();
            LambdaQueryWrapper<Theme> thirdThemeQuery = setThemeTreeQueryWrapper(planId, secondThemeId);
            List<Theme> thirdThemes = themeMapper.selectList(thirdThemeQuery);
            List<ThemeVO> thirdThemeVOS = themeConverter.themesToThemeVOs(thirdThemes);
            //设置三级主题
            secondThemeVO.setSubThemes(thirdThemeVOS);
        }
        //设置二级主题
        themeTreeVO.setSubThemes(secondThemeVOS);
        return themeTreeVO;
    }

    @Transactional
    @Override
    public AllThemeVO getAllThemeForPlan(Long planId) {
        try {
            AllThemeVO allThemeVO = new AllThemeVO();
            //统计总主题数
            LambdaQueryWrapper<Theme> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Theme::getPlanId, planId)
                    .eq(Theme::getStatus, 1);
            int totalThemes = Math.toIntExact(themeMapper.selectCount(queryWrapper));
            allThemeVO.setTotalThemes(totalThemes);

            //筛选出二级主题
            LambdaQueryWrapper<Theme> secondThemeQuery = setThemeTreeQueryWrapper(planId, 0L);
            List<Theme> secondThemes = themeMapper.selectList(secondThemeQuery);
            List<ThemeV2VO> secondThemeVOS = themeConverter.themesToThemeV2VOs(secondThemes);

            //拿到计划的currentModule
            Plan plan = planMapper.selectById(planId);
            Long currentModule = plan.getCurrentModule();
            for (ThemeV2VO secondThemeVO : secondThemeVOS) {
                //筛选出三级主题
                Long secondThemeId = secondThemeVO.getThemeId();
                LambdaQueryWrapper<Theme> thirdThemeQuery = setThemeTreeQueryWrapper(planId, secondThemeId);
                List<Theme> thirdThemes = themeMapper.selectList(thirdThemeQuery);
                List<SubThemeVO> thirdThemeVOS = themeConverter.themesToSubThemeVOs(thirdThemes);
                    for (SubThemeVO subThemeVO : thirdThemeVOS){
                        //拿到测验完成情况
                        TestInfoDTO testInfo = this.getThemeTestInfo(subThemeVO.getSubThemeId());
                        subThemeVO.setTestInfo(testInfo);
                        //拿到最近七天学习时间
                        ThemeStudyTimeVO studyInfo = this.getStudyInfo(subThemeVO.getSubThemeId());
                        subThemeVO.setStudyTime(studyInfo.getStudyTime());
                        if (subThemeVO.getSubThemeId().equals(currentModule)){
                            subThemeVO.setCurrent(true);
                            secondThemeVO.setCurrent(true);
                        }
                    }
                //设置三级主题
                secondThemeVO.setSubThemes(thirdThemeVOS);
            }
            allThemeVO.setThemes(secondThemeVOS);
            return allThemeVO;
        } catch (Exception e){
            throw new BusinessException("获取该计划所有子主题失败主题失败");
        }
    }

    private TestInfoDTO getThemeTestInfo(Long subThemeId) {
        try{

            int allQuiz = 0;      // 总问题数
            int completedQuiz = 0;   // 已完成的问题数

                LambdaQueryWrapper<Paper> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(Paper::getThemeId, subThemeId)
                        .eq(Paper::getStatus, 1)
                        .eq(Paper::getPaperType, 0);    // 0是测验，1是抽验卡
                allQuiz += Math.toIntExact(paperMapper.selectCount(lambdaQueryWrapper)) ;

                lambdaQueryWrapper.eq(Paper::getIsComplete, 1);
                completedQuiz += Math.toIntExact(paperMapper.selectCount(lambdaQueryWrapper));

            int unFinishedQuiz = allQuiz - completedQuiz;     // 未完成问题数


            return new TestInfoDTO(allQuiz, completedQuiz, unFinishedQuiz);

        }catch (Exception e){
            throw new BusinessException("获取主题测验情况失败");
        }
    }


    private LambdaQueryWrapper<Theme> setThemeTreeQueryWrapper(Long planId,Long superiorThemeId){
        LambdaQueryWrapper<Theme> queryWrapper = new LambdaQueryWrapper<>();
        //通过计划id筛选
        queryWrapper.eq(Theme::getPlanId, planId);
        //通过上级主题id筛选
        queryWrapper.eq(Theme::getSuperiorThemeId,superiorThemeId);
        //根据主题id进行排序
        queryWrapper.orderByAsc(Theme::getThemeId);
        //筛选出有效的测验
        queryWrapper.eq(Theme::getStatus, 1);
        return queryWrapper;
    }



    @Override
    @Transactional
    public boolean updateThemeStatus(SetThemeStatusRequest setThemeStatusRequest) {
        try {
            Theme theme = themeMapper.selectById(setThemeStatusRequest.getThemeId());
            Theme supTheme = themeMapper.selectById(theme.getSuperiorThemeId());
            theme.setCompletionStatus(setThemeStatusRequest.getCompletionStatus());
            themeMapper.updateById(theme);
            //如果请求的第三级主题的状态是进行中，则其上级主题也变为进行中
            if ((setThemeStatusRequest.getCompletionStatus() == 1 || setThemeStatusRequest.getCompletionStatus() == 2 )&& supTheme.getCompletionStatus() == 0){
                supTheme.setCompletionStatus(1);
            }
            //如果第三级主题全面完成，则父级主题已完成
            if (setThemeStatusRequest.getCompletionStatus() == 2){
                int i = 0;
                List<Theme> themes = themeMapper.selectList(setThemeTreeQueryWrapper(theme.getPlanId(), supTheme.getThemeId()));
                for (Theme subTheme : themes) {
                    if (subTheme.getCompletionStatus() != 2){
                        break;
                    }
                    i++;
                }
               if (i == themes.size()){
                   supTheme.setCompletionStatus(2);
               }
            }
            themeMapper.updateById(supTheme);
            return true;
        } catch (Exception e) {
            throw new BusinessException("更改主题状态失败失败");
        }
    }

    @Transactional
    @Override
    public boolean updateThemeStatusV2(UpdateThemeStatusRequest updateThemeStatusRequest) {
        try {
            Theme theme = themeMapper.selectById(updateThemeStatusRequest.getThemeId());
            Theme supTheme = themeMapper.selectById(theme.getSuperiorThemeId());

            //修改子主题状态
            int statusValue = ThemeCompletionStatus.fromTitle(updateThemeStatusRequest.getStatus()).getValue();
            theme.setCompletionStatus(statusValue);
            themeMapper.updateById(theme);
            List<Theme> themes = themeMapper.selectList(setThemeTreeQueryWrapper(theme.getPlanId(), supTheme.getThemeId()));

            //如果第三级主题是修改为完成时，二级主题判断变化
            setSupThemeFromTheme(statusValue,ThemeCompletionStatus.COMPLETED, supTheme, themes);

            //如果第三级主题是修改为未开始时，二级主题判断变化
            setSupThemeFromTheme(statusValue,ThemeCompletionStatus.NOT_STARTED, supTheme, themes);

            themeMapper.updateById(supTheme);
            //重新计算计划进度
            Plan plan = planMapper.selectById(theme.getPlanId());
            plan.setCompletionProgress(countPlanProgress(theme.getPlanId()));
            planMapper.updateById(plan);
            return true;
        } catch (Exception e) {
            throw new BusinessException("更改主题状态失败失败");
        }
    }

    private static void setSupThemeFromTheme(int statusValue, ThemeCompletionStatus judgeType,Theme supTheme, List<Theme> themes) {
        //如果请求的第三级主题的修改状态不是该状态，则其上级主题却是该状态
        if (statusValue != judgeType.getValue()  && supTheme.getCompletionStatus() == judgeType.getValue()){
            //将上级主题变为中间状态IN_PROGRESS
            supTheme.setCompletionStatus(ThemeCompletionStatus.IN_PROGRESS.getValue());
        }
        //对父级主题下的子主题进行判断，是否全部该状态，是的话父主题变为该状态
        if (statusValue == judgeType.getValue()){
            int i = 0;
            for (Theme subTheme : themes) {
                if (subTheme.getCompletionStatus() != judgeType.getValue()){
                    break;
                }
                i++;
            }
            if (i == themes.size()){
                supTheme.setCompletionStatus(judgeType.getValue());
            }
        }
    }


    @Override
    @Transactional
    public boolean deleteTheme(Long themeId) {
        Theme theme = themeMapper.selectById(themeId);
        theme.setStatus(0);
        themeMapper.updateById(theme);
        //将子主题状态也设为0
        LambdaUpdateWrapper<Theme> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Theme::getSuperiorThemeId,theme.getThemeId());
        updateWrapper.set(Theme::getStatus,0);
        themeMapper.update(null,updateWrapper);
        return true;
    }

    @Override
    @Transactional
    public boolean deleteThemeV2(Long themeId) {
        Theme theme = themeMapper.selectById(themeId);
        theme.setStatus(0);
        themeMapper.updateById(theme);
        //将子主题状态也设为0
        LambdaUpdateWrapper<Theme> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Theme::getSuperiorThemeId,theme.getThemeId());
        updateWrapper.set(Theme::getStatus,0);
        themeMapper.update(null,updateWrapper);
        //重新计算计划进度
        Plan plan = planMapper.selectById(theme.getPlanId());
        plan.setCompletionProgress(countPlanProgress(theme.getPlanId()));
        planMapper.updateById(plan);
        return true;
    }

    /**
     * 对主题学习时间进行处理
     * 进入主题学习，第一次保存学习时间为开始时间，不是第一次保存学习时间为结束时间
     *
     * @param themeId       主题id
     * @param status        判断时间状态：1-> 开始时间
     */
    @Override
    @Transactional
    public void themeStudyTime(Long themeId, Integer status) {
        try{
//            LocalDateTime studyTime = LocalDateTime.now();
//            LocalDate today = studyTime.toLocalDate();
            Instant studyTime = Instant.now();
            // 用ZoneId指明需要转换哪个时区
            LocalDate today = LocalDate.now(ZoneId.systemDefault());

            ThemeStudyTimeDTO studyTimeDTO = themeStudyTimeRepository.findByThemeIdAndToday(themeId, today);


            if (StringUtils.isNull(studyTimeDTO) ){
                // 没有学习时间记录
                ThemeStudyTimeDTO themeStudyTimeDTO = new ThemeStudyTimeDTO(themeId, today, studyTime);
                themeStudyTimeRepository.insert(themeStudyTimeDTO);

            } else if (status == 1) {
                // 更新开始时间
                studyTimeDTO.setStartTime(studyTime);
                themeStudyTimeRepository.save(studyTimeDTO);

            } else{
                // 更新结束时间
                studyTimeDTO.setEndTime(studyTime);
                themeStudyTimeRepository.save(studyTimeDTO);
            }

        }catch ( Exception e ){
            throw new BusinessException("更新主题学习时间异常");
        }
    }

    /**
     * 根据主题id，查找最近七天的学习时间
     * 根据planId，查找测验的完成情况
     *
     * @param themeId   主题id
     * @return          VO
     */
    @Override
    public ThemeStudyTimeVO getStudyInfo(Long themeId) {
        try{
            TreeMap<String, Integer> studyTimeMap = new TreeMap<>(Comparator.reverseOrder());

            Sort sort = Sort.by(Sort.Direction.DESC, "today");
            List<ThemeStudyTimeDTO> studyTimeDTOList = themeStudyTimeRepository.findByThemeId(themeId, sort);

            // 初始化VO
            LocalDate currentDay = LocalDate.now();
            for (int i = 0; i < 7; i++) {
                String dayTime = String.valueOf(currentDay.minusDays(i));
                studyTimeMap.put(dayTime, 0);
            }

            // 存在主题学习时间记录
            if(!studyTimeDTOList.isEmpty()){
                for (ThemeStudyTimeDTO studyTimeDTO : studyTimeDTOList){
                    int totalTime = studyTimeDTO.getTotalTime();
                    String dayTime = String.valueOf(studyTimeDTO.getToday());

                    studyTimeMap.replace(dayTime, totalTime);
                }
            }


            return new ThemeStudyTimeVO(themeId, studyTimeMap);

        }catch ( Exception e){
            throw new BusinessException("获取主题学习时间异常");
        }

    }
}




